package com.axeiya.cheddargetter;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.httpclient.methods.PostMethod;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.xpath.XPath;

public class CGTools {
	private static DateFormat m_ISO8601Local = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

	public static ArrayList<PricingPlan> getAllPricingPlans(String productCode) {
		try {
			PostMethod method = new PostMethod("/xml/plans/get/productCode/"
					+ productCode.toUpperCase());
			Element responseRoot = CheddarGetterClient.execute(method);

			ArrayList<PricingPlan> pricingPlansList = new ArrayList<PricingPlan>();
			List<Element> plansList = XPath.selectNodes(responseRoot, "//plan");

			for (Element plan : plansList) {

				PricingPlan pricingPlan = PricingPlan.parse(plan);
				pricingPlansList.add(pricingPlan);

			}

			return pricingPlansList;
		} catch (JDOMException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;

	}

	public static PricingPlan getPricingPlan(String productCode, String pricingPlanCode) {
		PostMethod method = new PostMethod("/xml/plans/get/productCode/"
				+ productCode.toUpperCase() + "/code/" + pricingPlanCode.toUpperCase());
		Element responseRoot = CheddarGetterClient.execute(method);

		return PricingPlan.parse(responseRoot.getChild("plan"));

	}

	public static ArrayList<Customer> getAllCustomers(String productCode) {
		PostMethod method = new PostMethod("/xml/customers/get/productCode/"
				+ productCode.toUpperCase());
		Element responseRoot = CheddarGetterClient.execute(method);
		List<Element> elements = responseRoot.getChildren("customer");
		ArrayList<Customer> customersList = new ArrayList<Customer>();
		for (Element element : elements) {
			customersList.add(Customer.parseCustomer(element));
		}

		return customersList;
	}

	public static Customer getSingleCustomer(String productCode, String customerCode) {
		PostMethod method = new PostMethod("/xml/customers/get/productCode/"
				+ productCode.toUpperCase() + "/code/" + customerCode.toUpperCase());

		Element responseRoot = CheddarGetterClient.execute(method);
		return Customer.parseCustomer(responseRoot.getChild("customer"));
	}

	public static void createNewCustomer(String productCode, Customer customer,
			ArrayList<Charge> charges, ArrayList<Item> items) {
		PostMethod method = new PostMethod("/xml/customers/new/productCode/" + productCode.toUpperCase());

		HashMap<String, String> customerParameters = Customer.formatCustomer(customer,
				Customer.FormatType.CREATE);

		for (String key : customerParameters.keySet()) {
			method.setParameter(key, customerParameters.get(key));
		}

		if (customer.getSubscriptions().size() == 1) {
			Subscription subscription = customer.getSubscriptions().get(0);
			HashMap<String, String> subscriptionsParameters;
			if (subscription.isFreePlan()) {
				subscriptionsParameters = Subscription.formatSubscription(customer
						.getSubscriptions().get(0), Subscription.FormatType.CREATEFREE);
			} else {
				subscriptionsParameters = Subscription.formatSubscription(customer
						.getSubscriptions().get(0), Subscription.FormatType.CREATE);
			}
			for (String key : subscriptionsParameters.keySet()) {
				method.setParameter("subscription[" + key + "]", subscriptionsParameters.get(key));
			}
		} else {
			// TODO : throw Exception ONE AND ONE ONLY subscription on creation
		}

		if (charges != null && charges.size() > 0) {
			for (Charge charge : charges) {
				HashMap<String, String> chargesParameters = Charge.formatCharge(charge);
				for (String key : chargesParameters.keySet()) {
					method.setParameter("charges[" + charge.getCode() + "][" + key + "]",
							chargesParameters.get(key));
				}
			}
		}

		if (items != null && items.size() > 0) {
			for (Item item : items) {
				HashMap<String, String> itemsParameters = Item.formatItem(item);
				for (String key : itemsParameters.keySet()) {
					method.setParameter("items[" + item.getItemCode() + "][" + key + "]",
							itemsParameters.get(key));
				}
			}
		}

		CheddarGetterClient.execute(method);
	}

	public static void updateCustomerAndSubscription(String productCode, Customer customer) {
		if (customer.getCode() != null && !customer.getCode().isEmpty()) {
			PostMethod method = new PostMethod("/xml/customers/edit/productCode/" + productCode.toUpperCase()
					+ "/code/" + customer.getCode().toUpperCase());

			HashMap<String, String> customerParameters = Customer.formatCustomer(customer,
					Customer.FormatType.UPDATE);

			for (String key : customerParameters.keySet()) {
				method.setParameter(key, customerParameters.get(key));
			}

			if (customer.getSubscriptions().size() == 1) {
				Subscription subscription = customer.getSubscriptions().get(0);
				HashMap<String, String> subscriptionsParameters;
				if (subscription.isFreePlan()) {
					subscriptionsParameters = Subscription.formatSubscription(subscription,
							Subscription.FormatType.UPDATEFREE);
				} else {
					subscriptionsParameters = Subscription.formatSubscription(subscription,
							Subscription.FormatType.UPDATE);
				}
				for (String key : subscriptionsParameters.keySet()) {
					method.setParameter("subscription[" + key + "]",
							subscriptionsParameters.get(key));
				}
			} else {
				// TODO : throw Exception ONE AND ONE ONLY subscription on
				// creation
			}
		} else {
			// TODO: throw new Exception
		}
	}

	public static void updateCustomer(String productCode, Customer customer) {
		if (customer.getCode() != null && !customer.getCode().isEmpty()) {
			PostMethod method = new PostMethod("/xml/customers/edit/productCode/" + productCode.toUpperCase()
					+ "/code/" + customer.getCode().toUpperCase());

			HashMap<String, String> customerParameters = Customer.formatCustomer(customer,
					Customer.FormatType.UPDATE);

			for (String key : customerParameters.keySet()) {
				method.setParameter(key, customerParameters.get(key));
			}

		} else {
			// TODO: throw new Exception
		}
	}

	public static void updateSubscription(String productCode, String customerCode,
			Subscription subscription) {
		PostMethod method = new PostMethod("/xml/customers/edit-subscription/productCode/"
				+ productCode.toUpperCase() + "/code/" + customerCode.toUpperCase());

		HashMap<String, String> subscriptionsParameters;
		if (subscription.isFreePlan()) {
			subscriptionsParameters = Subscription.formatSubscription(subscription,
					Subscription.FormatType.UPDATEFREE);
		} else {
			subscriptionsParameters = Subscription.formatSubscription(subscription,
					Subscription.FormatType.UPDATE);
		}
		for (String key : subscriptionsParameters.keySet()) {
			method.setParameter("key", subscriptionsParameters.get(key));
		}

	}

	public static void deleteCustomer(String productCode, String customerCode) {
		PostMethod method = new PostMethod("/xml/customers/delete/productCode/"
				+ productCode.toUpperCase() + "/code/" + customerCode.toUpperCase());
		CheddarGetterClient.execute(method);
	}

	public static void deleteAllCustomers(String productCode) {
		PostMethod method = new PostMethod("/xml/customers/delete-all/confirm/1/productCode/"
				+ productCode.toUpperCase());
		CheddarGetterClient.execute(method);
	}

	public static void cancelSubscription(String productCode, String customerCode) {
		PostMethod method = new PostMethod("/xml/customers/cancel/productCode/"
				+ productCode.toUpperCase() + "/code/" + customerCode.toUpperCase());
		CheddarGetterClient.execute(method);
	}

	public static void addItemQuantity(String productCode, String customerCode, String itemCode,
			int quantity) {
		PostMethod method = new PostMethod("/xml/customers/add-item-quantity/productCode/"
				+ productCode.toUpperCase() + "/code/" + customerCode.toUpperCase() + "/itemCode/" + itemCode.toUpperCase());

		method.setParameter("quantity", String.valueOf(quantity));

		CheddarGetterClient.execute(method);
	}

	public static void addItemQuantity(String productCode, String customerCode, String itemCode) {
		PostMethod method = new PostMethod("/xml/customers/add-item-quantity/productCode/"
				+ productCode.toUpperCase() + "/code/" + customerCode.toUpperCase() + "/itemCode/" + itemCode.toUpperCase());

		CheddarGetterClient.execute(method);
	}

	public static void removeItemQuantity(String productCode, String customerCode, String itemCode,
			int quantity) {
		PostMethod method = new PostMethod("/xml/customers/remove-item-quantity/productCode/"
				+ productCode.toUpperCase() + "/code/" + customerCode.toUpperCase() + "/itemCode/" + itemCode.toUpperCase());

		method.setParameter("quantity", String.valueOf(quantity));

		CheddarGetterClient.execute(method);
	}

	public static void removeItemQuantity(String productCode, String customerCode, String itemCode) {
		PostMethod method = new PostMethod("/xml/customers/remove-item-quantity/productCode/"
				+ productCode.toUpperCase() + "/code/" + customerCode.toUpperCase() + "/itemCode/" + itemCode.toUpperCase());

		CheddarGetterClient.execute(method);
	}

	public static void setItemQuantity(String productCode, String customerCode, String itemCode,
			int quantity) {
		PostMethod method = new PostMethod("/xml/customers/set-item-quantity/productCode/"
				+ productCode.toUpperCase() + "/code/" + customerCode.toUpperCase() + "/itemCode/" + itemCode.toUpperCase());

		method.setParameter("quantity", String.valueOf(quantity));

		CheddarGetterClient.execute(method);
	}

	public static void addCustomerChargeOrCredit(String productCode, String customerCode, String itemCode, Charge charge) {
		PostMethod method = new PostMethod("/xml/customers/add-charge/productCode/" + productCode.toUpperCase() + "/code/" + customerCode.toUpperCase() + "/itemCode/" + itemCode.toUpperCase());
		
		HashMap<String, String> parameters = Charge.formatCharge(charge);
		for (String key : parameters.keySet()) {
			method.setParameter(key, parameters.get(key));
		}
		
		CheddarGetterClient.execute(method);
	}

	// UTILS
	public static boolean parseBoolean(String booleanString) {
		if (booleanString.equals("0")) {
			return false;
		} else if (booleanString.equals("1")) {
			return true;
		} else {
			return Boolean.parseBoolean(booleanString);
		}
	}

	public static int formatBoolean(boolean value) {
		if (value)
			return 1;
		else
			return 0;
	}

	public static String formatDateTime() {
		return formatDateTime(new Date());
	}

	public static String formatDateTime(Date date) {
		if (date == null) {
			return formatDateTime(new Date());
		}

		// format in (almost) ISO8601 format
		String dateStr = m_ISO8601Local.format(date);

		// remap the timezone from 0000 to 00:00 (starts at char 22)
		return dateStr.substring(0, 22) + ":" + dateStr.substring(22);
	}

	public static Date parseDateTime(String dateString) {
		dateString = dateString.substring(0, 22) + dateString.substring(23);
		try {
			return m_ISO8601Local.parse(dateString);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

}
